﻿///@author Rafał Hazan
///@email  rafal.hazan@gmail.com
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>


#include "GraphBuilder.h"
#include "MatrixGraph.h"
#include "BadGraphFormatException.h"


GraphBuilder::~GraphBuilder()
    throw()
{
}

MatrixGraph* GraphBuilder::buildFromFile(std::ifstream & input)
{
	std::vector<MatrixGraph::V> firstRow = getFirstRow(input);
	int graphSize = firstRow.size();
	MatrixGraph * graph = new MatrixGraph(graphSize);
	for(int i = 0; i < graphSize; ++i)
	{
		if (firstRow[i] != 0)
		{
			graph->setEdge(0, i, 1);
		}
		else
		{
			graph->setEdge(0, i, 0);
		}
	}
	std::string nextLine;
	int leftRowsNo = graphSize - 1;
	while (getline(input, nextLine))
	{
		if (leftRowsNo == 0)
		{
			throw BadGraphFormatException("Macierz grafu nie jest kwadratowa. Zbyt duża liczba wierszy.");
		}
		std::stringstream ss(nextLine);
		MatrixGraph::V tmp;
		int column = 0;
		while ( !ss.eof() )
		{
			if ((ss >> tmp).fail())
			{
				throw BadGraphFormatException("Komórki macierzy grafu są podane w nieprawidłowym formacie.");
			}
			if (column >= graphSize)
			{
				throw BadGraphFormatException("Macierz grafu nie jest kwadratowa. Niektóre wiersze są zbyt długie.");
			}
			if (tmp != 0)
			{
				graph->setEdge(graphSize - leftRowsNo, column, 1);
			}
			else 
			{
				graph->setEdge(graphSize - leftRowsNo, column, 0);
			}
			++column;
		}
		if (column < graphSize)
		{
			throw BadGraphFormatException("Macierz grafu nie jest kwadratowa. Niektóre wiersze są zbyt krótkie.");
		}
		--leftRowsNo;
	}
	if (leftRowsNo > 0)
	{
		throw BadGraphFormatException("Macierz grafu nie jest kwadratowa. Zbyt duża liczba kolumn.");
	}
	//graph->print();
	std::cout << "wielkosc grafu " << graph->getVSize() << " " << graph->getVSize() << std::endl;

	return graph;
}

std::vector<MatrixGraph::V> GraphBuilder::getFirstRow(std::ifstream & input)
{
	std::string line;
	std::getline(input, line);
	std::vector<MatrixGraph::V> tokens;
	std::stringstream ss(line);
    std::string item;
	while ( !ss.eof() )
	{
		MatrixGraph::V tmp;
		if ((ss >> tmp).fail())
		{
			throw BadGraphFormatException("Komórki macierzy grafu są podane w nieprawidłowym formacie.");
		}
		tokens.push_back(tmp);
	}

	return tokens;
}